package com.lidx.back.statistics.utils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.BeanUtils;

//XXX
public class BeanCopyUtils {

	private static final Logger logger = LogManager.getLogger(BeanCopyUtils.class);

	/**
	 * 鎶�瀵硅薄涓墍鏈夊睘鎬т负 null 鐨勮浆涓洪潪null,鑻ヤ负bean瀵硅薄鍒欒瀵硅薄鐨勬墍鏈夊�涓虹┖
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static void nullConverEmpty(Object obj) {
		if (obj != null) {
			Class srcClass = obj.getClass();
			Method[] methods = srcClass.getDeclaredMethods();
			List<String> getMethodList = new ArrayList<String>();
			List<String> setMethodList = new ArrayList<String>();
			if (null != methods && methods.length > 0) {
				for (Method method : methods) {
					String methodName = method.getName().substring(method.getName().lastIndexOf(".") + 1);
					if (methodName.startsWith("set")) {
						setMethodList.add(methodName);
					} else if (methodName.startsWith("get")) {
						getMethodList.add(methodName);
					}
				}
			}
			// 鑾峰彇鎵�湁璇ュ璞＄殑灞炴�
			Field[] fields = srcClass.getDeclaredFields();

			// 閬嶅巻鎵�湁鐨勫睘鎬�
			for (Field field : fields) {
				String propertyName = field.getName();
				String getMethodName = "get" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
				String setMethodName = "set" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
				try {
					if (getMethodList.contains(getMethodName) && setMethodList.contains(setMethodName)) {
						Class propertyClass = field.getType();
						Method setMethod = srcClass.getDeclaredMethod(setMethodName, propertyClass);
						Method getMethod = srcClass.getMethod(getMethodName);
						Object propertyValue = getMethod.invoke(obj);// 璋冪敤璇ュ瓧娈电殑get鏂规硶
						if (null == propertyValue) {
							if (propertyClass.getName().equals("java.lang.String")) {
								setMethod.invoke(obj, "");
							} else if (propertyClass.getName().equals("java.util.List")) {
								setMethod.invoke(obj, new ArrayList());
							} else if (propertyClass.getName().equals("java.util.Map")) {
								setMethod.invoke(obj, new HashMap());
							} else if (propertyClass.getName().equals("int")) {
								setMethod.invoke(obj, 0);
							} else {
								Object propertyObj = propertyClass.newInstance();
								nullConverEmpty(propertyObj);
								setMethod.invoke(obj, propertyObj);
							}
						} else if (!propertyClass.getName().equals("java.lang.String") && !propertyClass.getName().equals("int")) {
							nullConverEmpty(propertyValue);
						}
					}
				} catch (Exception e) {
					logger.error("nullConverEmpty error", e);
				}
			}
		}
	}

	/**
	 * 鎷疯礉婧愬璞＄殑鎵�湁灞炴�鍒扮洰鏍囧璞′腑锛屽瀛樺湪鏈嫹璐濈殑灞炴�锛岃繑鍥瀎alse
	 * 
	 * @param source
	 * @param target
	 * @return
	 */

	public static boolean copyAllPropertiesTo(Object source, Object target) {
		boolean noError = true;
		PropertyDescriptor[] sourcePds = BeanUtils.getPropertyDescriptors(source.getClass());
		for (PropertyDescriptor sourcePd : sourcePds) {
			if ("class".equals(sourcePd.getName())) {
				continue;
			}
			Method readMethod = sourcePd.getReadMethod();
			PropertyDescriptor targetPd = BeanUtils.getPropertyDescriptor(target.getClass(), sourcePd.getName());
			Method writeMethod = targetPd.getWriteMethod();
			try {
				writeMethod.invoke(target, readMethod.invoke(source));
			} catch (Exception e) {
				noError = false;
				logger.error("Bean Copy error. ", e);
			}
		}
		return noError;
	}
	
	/**
	 * 鎷疯礉婧愬璞＄殑灞炴�鍒扮洰鏍囧璞＄殑鐩稿悓灞炴�涓紝濡傚瓨鍦ㄦ湭鎷疯礉鐨勫睘鎬э紝杩斿洖false
	 * 
	 * @param source
	 * @param target
	 * @return
	 */

	public static boolean copySamePropertiesTo(Object source, Object target) {
		boolean noError = true;
		PropertyDescriptor[] sourcePds = BeanUtils.getPropertyDescriptors(source.getClass());
		for (PropertyDescriptor sourcePd : sourcePds) {
			if ("class".equals(sourcePd.getName())) {
				continue;
			}
			Method readMethod = sourcePd.getReadMethod();
			PropertyDescriptor targetPd = BeanUtils.getPropertyDescriptor(target.getClass(), sourcePd.getName());
			if(null != targetPd){
				Method writeMethod = targetPd.getWriteMethod();
				try {
					writeMethod.invoke(target, readMethod.invoke(source));
				} catch (Exception e) {
					noError = false;
					logger.error("Bean Copy error. ", e);
				}
			}
		}
		return noError;
	}

	public static <T> T populateBean(Class<T> beanClass, Map<String, String> map) {
		try {
			T resultObj = beanClass.newInstance();
			PropertyDescriptor[] beanPds = BeanUtils.getPropertyDescriptors(beanClass);
			for (PropertyDescriptor sourcePd : beanPds) {
				String pName = sourcePd.getName();
				if ("class".equals(pName)) {
					continue;
				}
				Method writeMethod = sourcePd.getWriteMethod();
				String value = map.get(pName);
				if (value != null) {
					writeMethod.invoke(resultObj, value);
				}
			}
			return resultObj;
		} catch (Exception e) {
			logger.error("Bean populate error. ", e);
			return null;
		}
	}

}
